home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / clu / debug2.clu < prev    next >
Text File  |  1993-07-25  |  24KB  |  850 lines

  1.  
  2. % clusters & procs to support debug.clu
  3. estack = cluster is create, addh, top, bottom, fetch, size, push, trim,
  4.             elements, store
  5.  
  6.     rep = array[dexpr]
  7.  
  8.     create = proc() returns (cvt)
  9.     return(rep$new())
  10.     end create
  11.  
  12.     push = proc(a: cvt, e: dexpr)
  13.     rep$addh(a, e)
  14.     end push
  15.  
  16.     addh = proc(a: cvt, e: dexpr)
  17.     rep$addh(a, e)
  18.     end addh
  19.  
  20.     top = proc(a:cvt) returns(dexpr)
  21.     return(rep$bottom(a))
  22.     end top
  23.  
  24.     bottom = proc(a:cvt) returns (dexpr)
  25.     return(rep$bottom(a))
  26.     end bottom
  27.  
  28.     fetch = proc(a:cvt, i: int) returns (dexpr)
  29.     return(rep$fetch(a, i))
  30.     end fetch
  31.  
  32.     store = proc(a:cvt, i: int, e: dexpr)
  33.     rep$store(a, i, e)
  34.     end store
  35.  
  36.     size = proc(a:cvt) returns(int)
  37.     return(rep$size(a))
  38.     end size
  39.  
  40.     trim = proc(es: cvt, start, cnt: int)
  41.     rep$trim(es, start, cnt)
  42.     end trim
  43.  
  44.     elements = iter(es: cvt) yields (dexpr)
  45.     for each_d: dexpr in rep$elements(es) do
  46.         yield(each_d)
  47.         end
  48.     end elements
  49.  
  50.     end estack
  51.  
  52. logit = proc(s: string)
  53.     own pe : stream := stream$error_output()
  54.  
  55.     stream$putl(pe, s)
  56.  
  57.     end logit
  58.  
  59. % needs to write output to a temp file in /tmp (or use mktemp/tempfile/tmpname)
  60.  
  61. sym = cluster is get_address, clear_owns, get_name
  62.  
  63.     rep = null
  64.  
  65.     cache_entry = record[name: string, address: int]
  66.     ace = array[cache_entry]
  67.     own st: stream
  68.     own init: bool := false
  69.     own pgm_name: string := ""
  70.     own cache: ace := ace$predict(1, 25)
  71.     own prefix: string := " "
  72.  
  73.     setup = proc()
  74.     % caller should set init flag
  75.     begin
  76.         pgm_name := _get_xjname()
  77.         loc: int := string_lindexs("/", pgm_name)
  78.         if loc < string$size(pgm_name) then
  79.         pgm_name := string$rest(pgm_name, loc+1)
  80.         end
  81.         fn: file_name := file_name$create("", pgm_name, "", "")
  82.         symfn: file_name := file_name$create("", pgm_name, "sym", "")
  83.         if file_exists(symfn) then
  84.            fn_date: date := file_date(fn, false)
  85.            sym_date: date := file_date(symfn, false)
  86.            if sym_date > fn_date then
  87.           exit done
  88.           end
  89.            end
  90.         unix_cmd("nm -B " || pgm_name || " </dev/null 2>/dev/null >" 
  91.                 || pgm_name || ".sym")
  92.         except others:
  93.                 unix_cmd("nm " || pgm_name || " </dev/null >" 
  94.                 || pgm_name || ".sym")
  95.             end
  96.         end
  97.        except when done: end
  98.     end setup
  99.  
  100.     get_address = proc(s: string) returns (int) signals (not_found)
  101.     
  102.     if ~init then
  103.        setup()
  104.        end
  105.  
  106.     % change $ to OP
  107.     n: int := string$indexc('$', s)
  108.     if n ~= 0 then
  109.        s := string$substr(s, 1, n-1) || "OP" || string$rest(s, n+1)
  110.        end
  111.     s := prefix || s
  112.     s_size: int := string$size(s)
  113.  
  114.     % first check cache
  115.     for each_ent: cache_entry in ace$elements(cache) do
  116.         if s = each_ent.name then return (each_ent.address) end
  117.         end
  118.     
  119.     while true do
  120.         st := stream$open(file_name$create("", pgm_name, "sym",""),"read")
  121.         while true do
  122.         l: string := stream$getl(st)
  123.         loc: int := string$indexs(s, l)
  124.         if loc = 0 then continue end
  125.         if string$size(l) - loc + 1 ~= s_size then continue end
  126.         sp: int := string$indexc(' ', l)
  127.         num: string := string$substr(l, 1, sp-1)
  128.         stream$close(st)
  129.         add: int := i_hparse(num)
  130.         ace$addh(cache, cache_entry${name: s, address: add})
  131.         init := true
  132.         return (add)
  133.         end
  134.            except when end_of_file:
  135.                stream$close(st)
  136.                if init
  137.                   then
  138.                    signal not_found
  139.                   else
  140.                    init := true
  141.                    prefix := " _"
  142.                    s := prefix || string$rest(s, 2)
  143.                    s_size := string$size(s)
  144.                   end
  145.               end
  146.         end
  147.     end get_address
  148.  
  149.     get_name = proc(addr: int) returns (string) signals (not_found)
  150.     if ~init then
  151.        setup()
  152.        end
  153.  
  154.     % first check cache
  155.     for each_ent: cache_entry in ace$elements(cache) do
  156.         if addr = each_ent.address then return (string$rest(each_ent.name, string$size(prefix)+1)) end
  157.         end
  158.     
  159.         s: string := slower(i_hunparse(addr))
  160.     s_size: int := string$size(s)
  161. %    if s_size ~= 8 then logit("losing in get_name: " || int$unparse(s_size) ||
  162. %                  " " || s) end
  163.     while true do
  164.         st := stream$open(file_name$create("", pgm_name, "sym",""),"read")
  165.         while true do
  166.         l: string := stream$getl(st)
  167.         loc: int := string$indexs(s, l)
  168.         if loc = 0 then continue end
  169.         if loc ~= 1 then logit ("losing (2) in get_name: " || int$unparse(loc)) end
  170.         sp: int := string_lindexs(prefix, l)
  171.         nm: string := string$rest(l, sp + string$size(prefix))
  172.         stream$close(st)
  173.         ace$addh(cache, cache_entry${name: prefix || nm, address: addr})
  174.         return (nm)
  175.         end
  176.            except when end_of_file:
  177.                signal not_found
  178.               end
  179.         end
  180.     end get_name
  181.  
  182.     clear_owns = proc()
  183.     if ~init then setup() init := true end
  184.     st := stream$open(file_name$create("", pgm_name, "sym",""),"read")
  185.     while true do
  186.         l: string := stream$getl(st)
  187.         ls: int := string$size(l)
  188.         if ls < 13 then continue end
  189.         if string_lindexs("_own_init", l) = ls - 8
  190.            then
  191.             sp: int := string$indexc(' ', l)
  192.             num: string := string$substr(l, 1, sp-1)
  193.             add: int := i_hparse(num)
  194.             debugOPassign(add, 0)
  195.            end
  196.         end
  197.        except when end_of_file:
  198.                stream$close(st)
  199.           end
  200.     end clear_owns
  201.     end sym
  202.  
  203.  
  204. internalize = proc(arg: string) returns (string)
  205.     arg := lower_case(arg)
  206.     index: int := string$indexc('$', arg)
  207.     if index ~= 0 then
  208.        return (string$substr(arg, 1, index - 1) || "OP" ||
  209.            string$rest(arg, index + 1))
  210.        else
  211.         return (arg)
  212.        end
  213.     end internalize
  214.  
  215. externalize = proc(arg: string) returns (string)
  216.     index: int := string$indexs("OP", arg)
  217.     if index ~= 0 then
  218.        return (string$substr(arg, 1, index - 1) || "$" ||
  219.            string$rest(arg, index + 2))
  220.        else
  221.         return (arg)
  222.        end
  223.     end externalize
  224.  
  225.  
  226. bkpts = cluster is clear, add, remove, exists, print, load, dump
  227.  
  228.     rep = abkpt
  229.  
  230.     as = array[string]
  231.     abkpt = array[bkpt]
  232.  
  233.     % probably should keep _TRACE address in rep, for speed in untracing
  234.     % possibly should keep bkpt in inactive state, rather than removing
  235.  
  236.     bkpt = oneof[line: lbkpt, func: fbkpt, step: sbkpt, temp: tbkpt]
  237.     lbkpt = record[line: int, mod: string] % line (break at line in mod
  238.     fbkpt = record[mod: string]           % func (break on entry/exit)
  239.     sbkpt = record[mod: string]           % step (break at all lines)
  240.     tbkpt = record[mod: string]           % temporary breakpoint
  241.  
  242.     own current_bkpts: rep := rep$predict(1,25)
  243.     own init: bool := false
  244.     own bkptfn: file_name
  245.     own tyo: stream
  246.  
  247.     setup = proc()
  248.     begin
  249.         pgm_name: string := _get_xjname()
  250.         loc: int := string_lindexs("/", pgm_name)
  251.         if loc < string$size(pgm_name) then
  252.         pgm_name := string$rest(pgm_name, loc+1)
  253.         end
  254.         bkptfn := file_name$create("", pgm_name, "bkpts", "")
  255.         end
  256.     init := true
  257.     end setup
  258.  
  259.     clear = proc()
  260.     off: as := as$predict(1,25)
  261.     for each_bkpt: bkpt in rep$elements(current_bkpts) do
  262.         found: bool
  263.         tagcase each_bkpt
  264.            tag step (s: sbkpt):
  265.            found := false
  266.            for n: string in as$elements(off) do
  267.                if n = s.mod then found := true break end
  268.                end
  269.            if ~found then as$addh(off, s.mod) end
  270.            tag line (l: lbkpt):
  271.            found := false
  272.            for n: string in as$elements(off) do
  273.                if n = l.mod then found := true break end
  274.                end
  275.            if ~found then as$addh(off, l.mod) end
  276.            tag temp (t: tbkpt):
  277.            found := false
  278.            for n: string in as$elements(off) do
  279.                if n = t.mod then found := true break end
  280.                end
  281.            if ~found then as$addh(off, t.mod) end
  282.            tag func (f: fbkpt):
  283.            end
  284.         end
  285.     for n: string in as$elements(off) do
  286.         line_tracing_off(n)
  287.         end
  288.     current_bkpts := rep$predict(1,25)
  289.     dump()
  290.     end clear
  291.  
  292.     load = proc(outst: stream)
  293.     if ~init then setup() end
  294.     tyo := outst
  295.     if ~file_exists(bkptfn) 
  296.        then
  297.         % stream$putl(tyo, "breakpoints file not found")
  298.         return
  299.        end
  300.     inst: stream := stream$open(bkptfn, "read")
  301.     while true do
  302.         l: string := stream$getl(inst)
  303.         args: as := parse_line(l)
  304.         if args[1] = "L"
  305.            then
  306.             if as$size(args) ~= 3 then
  307.                stream$putl(tyo, "bad format breakpoints file 1")
  308.                exit done
  309.                end
  310.             add(args[2], "l", int$parse(args[3]))
  311.                except when bad_format:
  312.                    stream$putl(tyo, "bad format integer in breakpoint file")
  313.                    exit done
  314.                   when not_found:
  315.                    stream$putl(tyo, "breakpoint " || args[2] ||
  316.                             " not found, continuing")
  317.                   end
  318.          elseif args[1] = "F"
  319.            then
  320.             if as$size(args) ~= 2 then
  321.                stream$putl(tyo, "bad format breakpoints file 2")
  322.                exit done
  323.                end
  324.             add(args[2], "f", 0)
  325.                except when not_found:
  326.                    stream$putl(tyo, "breakpoint " || args[2] ||
  327.                             " not found, continuing")
  328.                   end
  329.          elseif args[1] = "S"
  330.            then
  331.             if as$size(args) ~= 2 then
  332.                stream$putl(tyo, "bad format breakpoints file 3")
  333.                exit done
  334.                end
  335.             add(args[2], "s", 0)
  336.                except when not_found:
  337.                    stream$putl(tyo, "breakpoint " || args[2] ||
  338.                             " not found, continuing")
  339.                   end
  340.          else
  341.           stream$putl(tyo, "bad format breakpoints file 4")
  342.           exit done
  343.          end
  344.         end
  345.        except when done:
  346.           when end_of_file:
  347.                stream$close(inst)
  348.               except others: end
  349.                return
  350.           others (why: string):
  351.                stream$putl(tyo, "breakpoints file loading failed: " || why)
  352.                stream$close(inst)
  353.               except others: end
  354.                return
  355.           end
  356.     end load
  357.  
  358.     dump = proc()
  359.     if ~init then setup() end
  360.     outst_exists: bool := false
  361.     outst: stream
  362.     begin
  363.         if file_exists(bkptfn) then delete_file(bkptfn) end
  364.         outst := stream$open(bkptfn, "write")
  365.         outst_exists := true
  366.         for each_bkpt: bkpt in rep$elements(current_bkpts) do
  367.         tagcase each_bkpt
  368.            tag step (s: sbkpt):
  369.                stream$putl(outst, "S " || s.mod)
  370.            tag line (l: lbkpt):
  371.                stream$putl(outst, "L " || l.mod || " " || int$unparse(l.line))
  372.            tag func (f: fbkpt):
  373.                stream$putl(outst, "F " || f.mod)
  374.            tag temp:
  375.            end
  376.         end
  377.         stream$close(outst)
  378.         end
  379.        except others (errstr: string):
  380.                stream$putl(tyo, "break point dump failed: " || errstr)
  381.                if outst_exists then stream$close(outst) end
  382.               except others: end
  383.           end
  384.     end dump
  385.  
  386.     add = proc(mod, kind: string, line: int) signals (not_found)
  387.     if kind = "s" cand ~exists(mod, kind, line) then
  388.        line_tracing_on(mod)
  389.           resignal not_found
  390.        rep$addh(current_bkpts,
  391.             bkpt$make_step(sbkpt${mod: mod}))
  392.      elseif kind = "t" cand ~exists(mod, kind, line) then
  393.        line_tracing_on(mod)
  394.           resignal not_found
  395.        rep$addh(current_bkpts,
  396.             bkpt$make_temp(tbkpt${mod: mod}))
  397.      elseif kind = "f" cand ~exists(mod, kind, line) then
  398.        if func_exists(mod)
  399.           then
  400.            rep$addh(current_bkpts,
  401.                 bkpt$make_func(fbkpt${mod: mod}))
  402.           else signal not_found end
  403.      elseif kind = "l" cand ~exists(mod, kind, line) then
  404.        line_tracing_on(mod)
  405.           resignal not_found
  406.        rep$addh(current_bkpts,
  407.             bkpt$make_line(lbkpt${mod: mod, line: line}))
  408.      end
  409.     dump()
  410.     end add
  411.  
  412.     remove = proc(mod, kind: string, line: int) signals (not_found)
  413.     
  414.     % first remove the indicated breakpoint
  415.  
  416.     found: bool := false
  417.     for i: int in rep$indexes(current_bkpts) do
  418.         each_bkpt: bkpt := current_bkpts[i]
  419.         tagcase each_bkpt
  420.            tag step (s: sbkpt):
  421.            if kind = "s" cand s.mod = mod then
  422.               asize: int := rep$size(current_bkpts)
  423.               current_bkpts[i] := current_bkpts[asize]
  424.               rep$trim(current_bkpts, 1, asize - 1)
  425.               found := true
  426.               break
  427.               end
  428.            tag line (l: lbkpt):
  429.            if kind = "l" cand l.mod = mod
  430.             cand line = l.line
  431.               then
  432.                asize: int := rep$size(current_bkpts)
  433.                current_bkpts[i] := current_bkpts[asize]
  434.                rep$trim(current_bkpts, 1, asize - 1)
  435.                found := true
  436.                break
  437.               end
  438.            tag func (f: fbkpt):
  439.            if kind = "f" cand f.mod = mod then
  440.               asize: int := rep$size(current_bkpts)
  441.               current_bkpts[i] := current_bkpts[asize]
  442.               rep$trim(current_bkpts, 1, asize - 1)
  443.               found := true
  444.               break
  445.               end
  446.            tag temp (t: tbkpt):
  447.            if kind = "t" cand t.mod = mod then
  448.               asize: int := rep$size(current_bkpts)
  449.               current_bkpts[i] := current_bkpts[asize]
  450.               rep$trim(current_bkpts, 1, asize - 1)
  451.               found := true
  452.               break
  453.               end
  454.            end
  455.         end
  456.  
  457.     if ~found then signal not_found end
  458.     dump()
  459.  
  460.     % now decide whether to turn off line_tracing
  461.  
  462.     for i: int in rep$indexes(current_bkpts) do
  463.         each_bkpt: bkpt := current_bkpts[i]
  464.         tagcase each_bkpt
  465.            tag step (s: sbkpt):
  466.            if s.mod = mod then return end
  467.            tag line (l: lbkpt):
  468.            if mod = l.mod then return end
  469.            others:
  470.            end
  471.         end
  472.     line_tracing_off(mod)
  473.     end remove
  474.  
  475.     exists = proc(mod, kind: string, line: int) returns (bool)
  476.     for each_b: bkpt in rep$elements(current_bkpts) do
  477.         tagcase each_b
  478.            tag line (l: lbkpt):
  479.            if l.mod = mod cand kind = "l" cand line = l.line
  480.               then return (true) end
  481.            if l.mod = mod cand kind = "sl" cand line = l.line
  482.               then return (true) end
  483.            tag func (f: fbkpt):
  484.            if f.mod = mod cand kind = "f" then return (true) end
  485.            if f.mod = mod cand kind = "a" then return (true) end
  486.            tag step (s: sbkpt):
  487.            if s.mod = mod cand kind = "s" then return (true) end
  488.            if s.mod = mod cand kind = "sl" then return (true) end
  489.            if s.mod = mod cand kind = "a" then return (true) end
  490.            tag temp (t: tbkpt):
  491.            if t.mod = mod cand kind = "t" then return (true) end
  492.            if t.mod = mod cand kind = "sl" then return (true) end
  493.            if t.mod = mod cand kind = "a" then return (true) end
  494.            end
  495.         end % for
  496.     return (false)
  497.     end exists
  498.  
  499.     print = proc(st: stream)
  500.     stream$putl(st, "Breakpoints:")
  501.     for each_b: bkpt in rep$elements(current_bkpts) do
  502.         tagcase each_b
  503.            tag func (f: fbkpt):
  504.            stream$putl(st, "\t entry/exit: " || externalize(f.mod))
  505.            tag line (l: lbkpt):
  506.            stream$putl(st, "\t" || l.mod || " " || int$unparse(l.line))
  507.            tag step (s: sbkpt):
  508.            stream$putl(st, "\t single step: " || externalize(s.mod))
  509.            tag temp (t: tbkpt):
  510.            stream$putl(st, "\t temporary single step: " || externalize(t.mod))
  511.            end
  512.         end
  513.     end print
  514.  
  515.     func_exists = proc(mod: string) returns (bool)
  516.     addr: int := sym$get_address(mod)
  517.        except when not_found:
  518.                return (false)
  519.           end
  520.     return(true)
  521.     end func_exists
  522.  
  523.     line_tracing_on = proc(mod: string) signals (not_found)
  524.     addr: int := sym$get_address(mod || "_TRACE")
  525.        resignal not_found
  526.     debugOPassign(addr, 1)
  527.     end line_tracing_on
  528.  
  529.     line_tracing_off = proc(mod: string)
  530.     addr: int := sym$get_address(mod || "_TRACE")
  531.     debugOPassign(addr, 0)
  532.     end line_tracing_off
  533.  
  534.     end bkpts
  535.  
  536.  
  537. trace_pts = cluster is add, remove, print, exists, clear
  538.  
  539.     as = array[string]
  540.     rep = as
  541.  
  542.     own trpts: rep := rep$fill(1,1,"failure")
  543.     own all: bool := false
  544.  
  545.     add = proc(sig: string)
  546.     if sig = "all" then all := true return end
  547.     if ~exists(sig) then
  548.        rep$addh(trpts, sig)
  549.        end
  550.     end add
  551.  
  552.     exists = proc(sig: string) returns (bool)
  553.     if all  = true then return (true) end
  554.     for each: string in rep$elements(trpts) do
  555.         if each = sig then return (true) end
  556.         end
  557.     return(false)
  558.     end exists
  559.  
  560.     remove = proc(sig: string) signals (not_found)
  561.     if sig = "all" then all := false return end
  562.     for i: int in rep$indexes(trpts) do
  563.         each: string := trpts[i]
  564.         if each = sig then
  565.            tsize: int := rep$size(trpts)
  566.            trpts[i] := trpts[tsize]
  567.            rep$trim(trpts, 1, tsize - 1)
  568.            end
  569.         end
  570.     signal not_found
  571.     end remove
  572.  
  573.     clear = proc()
  574.     all := false
  575.     trpts := rep$fill(1,1,"failure")
  576.     end clear
  577.  
  578.     print = proc(st: stream)
  579.     stream$putl(st, "Traced Signals:")
  580.     for each_sig: string in rep$elements(trpts) do
  581.         stream$puts(st, "\t")
  582.         stream$putl(st, each_sig)
  583.         end
  584.     if all then
  585.        stream$putl(st, "\tall signals are being traced")
  586.        end
  587.     end print
  588.  
  589.     end trace_pts
  590.  
  591. opown2typeown = proc(nm: string) returns (string) signals (not_found)
  592.     % if nm is of the form aOPbOPc then return aOPc where a, b, c are arbitrary strings
  593.     %            and OP is exactly OP
  594.     % used for looking up own variables: aOPbOPc would be the full name
  595.     %    of the own variable named c in operation a$b
  596.     %    aOPc would be full name of an own variable c in cluster a
  597.     
  598.     lim: int := string$indexs("OP", nm)
  599.     if lim = 0 then signal not_found end    % shouldn't happen
  600.     tname: string := string$substr(nm, 1, lim - 1)
  601.     lim := string_lindexs("OP", nm)
  602.     vname: string := string$rest(nm, lim + 2)
  603.     return (tname || "OP" || vname)
  604.     end opown2typeown
  605.  
  606. print_uninit = proc(po: pstream, v:_obj)
  607.     pstream$text(po, "???")
  608.     end print_uninit
  609.  
  610. as = array[string]
  611. inst_from_info = proc(info:rtn_info, tparms, oparms: list) returns (int, int)
  612.     % do instantiation work
  613.     k: int := 0
  614.     nm: string := debugopget_name(info)
  615.     nm := externalize(nm)
  616.     loc: int := string$indexc('$', nm)
  617.     tname: string := ""
  618.     opname: string := nm
  619.     if loc ~= 0
  620.        then
  621.         tname := string$substr(nm, 1, loc - 1)
  622.         opname := string$rest(nm, loc + 1)
  623.        end
  624.     tformals: as := as$new()
  625.     for i: int in list$indexes(tparms) do
  626.     as$addh(tformals, debugOPget_nth_type_formal(info, i))
  627.     end
  628.     oformals: as := as$new()
  629.     for i: int in list$indexes(oparms) do
  630.     as$addh(oformals, debugOPget_nth_op_formal(info, i))
  631.     end
  632.     tops, oops: int := inst(tname, opname, tformals, oformals, tparms, oparms)
  633.     return(tops, oops)
  634.     end inst_from_info
  635.  
  636. inst_from_name = proc(aiops: string, info: rtn_info, itparms, ioparms: list) returns (int)
  637.     % find type name in aiops
  638.     % note: type name may be a parameter
  639.     loc: int := string$indexc('_', aiops)
  640.     tname: string := string$substr(aiops, 1, loc-1)
  641.  
  642.     % make list of components in aiops: 
  643.     %        some may be formals of invocation, some actuals
  644.     % note: there may be none
  645.     tcomps: as := as$new()
  646.     rest: string := string$rest(aiops, loc+1)
  647.     while true do
  648.     loc := string$indexc('_', rest)
  649.     if loc = 0 then break end
  650.     nth: string := string$substr(rest, 1, loc-1)
  651.     rest := string$rest(rest, loc+1)
  652.     if nth = "of" then continue end
  653.     as$addh(tcomps, nth)
  654.     end
  655.  
  656.     % make corresponding list of actuals via the following steps:
  657.  
  658.     % find list of all possible formals from invoked routine
  659.     itformals: as := as$new()
  660.     for i: int in list$indexes(itparms) do
  661.     as$addh(itformals, debugOPget_nth_type_formal(info, i))
  662.     end
  663.     ioformals: as := as$new()
  664.     for i: int in list$indexes(ioparms) do
  665.     as$addh(ioformals, debugOPget_nth_op_formal(info, i))
  666.     end
  667.  
  668.     % find corresponding list of actuals from invoked routine
  669.     %    (these are the itparms and ioparms arguments)
  670.  
  671.     % first check for tname member of itformals (and empty tcomps list)
  672.     if as$empty(tcomps) then
  673.        for i: int in as$indexes(itformals) do
  674.        if itformals[i] = tname then
  675.           d: dexpr := _cvt[_obj,dexpr](itparms[i])
  676.           tagcase d
  677.          tag idn (id: ident):
  678.              opers: int := sym$get_address(id || "_ops_actual")
  679.              return(opers)
  680.          others:
  681.              logit("still losing in inst_from_name (1)")
  682.          end
  683.           return(_cvt[_obj,int](itparms[i]))
  684.           end
  685.        end
  686.        for i: int in as$indexes(ioformals) do
  687.        if ioformals[i] = tname then
  688.           d: dexpr := _cvt[_obj,dexpr](ioparms[i])
  689.           tagcase d
  690.          tag idn (id: ident):
  691.              opers: int := sym$get_address(id || "_ops_actual")
  692.              return(opers)
  693.          others:
  694.              logit("still losing in inst_from_name (2)")
  695.          end
  696.           end
  697.        end
  698.        logit("still losing in inst_from_name (3)")
  699.        end
  700.  
  701.     % get formals for aiops
  702.     tformals: as := as$new()
  703.     aname: string := "tformals_" || tname
  704.     a: int := sym$get_address(aname)
  705.     for i: int in int$from_to(1, as$size(tcomps)) do
  706.     as$addh(tformals, debugopget_nth_formal(a, i))
  707.     end
  708.  
  709.     % intersect formals from invocation with formals needed
  710.     % and make list of corresponding actuals
  711.     tparms: list := list$new()
  712.     for formal: string in as$elements(tcomps) do
  713.     begin
  714.         for i: int in as$indexes(itformals) do
  715.         if itformals[i] = formal then
  716.            tparms := list$addh(tparms, itparms[i])
  717.            exit done
  718.            end
  719.         end
  720.         for i: int in as$indexes(ioformals) do
  721.         if ioformals[i] = formal then
  722.            tparms := list$addh(tparms, ioparms[i])
  723.            exit done
  724.            end
  725.         end
  726.         d: dexpr := dexpr$make_idn(formal)
  727.         dobj: _obj := _cvt[dexpr, _obj](d)
  728.         tparms := list$addh(tparms, dobj)
  729.         end except when done: continue end
  730.     end
  731.     tops, oops: int := inst(tname, "", tformals, as$new(), tparms, list$new())
  732.     return(tops)
  733.     end inst_from_name
  734.  
  735. inst = proc(tname, opname: string, tformals, oformals:as, tparms, oparms: list)
  736.      returns (int, int)
  737.     % do instantiation work
  738.     k: int := 0
  739.     i: int := 1
  740.     for each_dexpr: dexpr in dexprlist$elements(l2d(tparms)) do
  741.     tagcase each_dexpr
  742.        tag const (c: con):
  743.            iobj: _obj
  744.            tagcase c
  745.           tag int_(num: int):
  746.               iobj := _cvt[int, _obj](num)
  747.           others:
  748.               logit(" fill in others in const instantiation 1")
  749.           end
  750.            CLU_add_parm_info_const(k, iobj)
  751.        tag idn, tgen, sel:
  752.            opers: int := debug$teval(each_dexpr)
  753.            reqs: int := sym$get_address(tname || "_of_" ||
  754.                         tformals[i] || "_reqs_actual")
  755.            CLU_add_parm_info_type(k, opers, reqs)
  756.        others:
  757.            logit(" unexpected dexpr in instantiation list 1")
  758.        end
  759.     i := i + 1
  760.     k := k + 1
  761.     end
  762.     i := 1
  763.     for each_dexpr: dexpr in dexprlist$elements(l2d(oparms)) do
  764.     tagcase each_dexpr
  765.        tag const (c: con):
  766.            iobj: _obj
  767.            tagcase c
  768.           tag int_(num: int):
  769.               iobj := _cvt[int, _obj](num)
  770.           others:
  771.               logit(" fill in others in const instantiation 2")
  772.           end
  773.            CLU_add_parm_info_const(k, iobj)
  774.        tag idn (id: ident):
  775.            opers: int := sym$get_address(id || "_ops_actual")
  776.            reqs: int := sym$get_address(opname || "_of_" ||
  777.                         oformals[i] || "_reqs_actual")
  778.            CLU_add_parm_info_type(k, opers, reqs)
  779.        others:
  780.            logit(" unexpected dexpr in instantiation list 2")
  781.        end
  782.     i := i + 1
  783.     k := k + 1
  784.     end
  785.     % invoke appropriate instantiation operation
  786.     tops: int := 0
  787.     oops: int := 0
  788.     if dexprlist$size(l2d(tparms)) ~= 0
  789.        then
  790.         opers: int := sym$get_address(tname || "_ops_actual")
  791.         tcount: int := list$size(tparms)
  792.         ownreqs: int := sym$get_address(tname || "_ownreqs")
  793.         tops := clu_find_type_instance(opers, tcount, ownreqs)
  794.         if dexprlist$size(l2d(oparms)) ~= 0
  795.            then
  796.             opownreqs: int := sym$get_address(tname || "_op_"
  797.                             || opname || "_ownreqs")
  798.             opaddr: int := sym$get_address(tname || "OP" || opname)
  799.             ocount: int := dexprlist$size(l2d(oparms))
  800.             oops := clu_find_typeop_instance(opers, opaddr,
  801.                          tcount+ocount, tcount, opownreqs, ownreqs)
  802.            end
  803.        else % no type parameters
  804.         if list$size(oparms) ~= 0
  805.            then
  806.             opownreqs: int := sym$get_address(opname || "_ownreqs")
  807.             opaddr: int := sym$get_address(opname)
  808.             ocount: int := dexprlist$size(l2d(oparms))
  809.             oops := clu_find_prociter_instance(opaddr, ocount, opownreqs)
  810.            end
  811.        end
  812.     return(tops, oops)
  813.     end inst
  814.  
  815. iter_yield = cluster is setup, print
  816.     rep = null
  817.     own valops: ops
  818.     own tparms: list
  819.     own oparms: list
  820.     own info: rtn_info
  821.     own po: pstream
  822.  
  823.     setup = proc(val_ops:ops, t_parms, o_parms:list, inf:rtn_info, pstr: pstream)
  824.     valops := val_ops
  825.     tparms := t_parms
  826.     oparms := o_parms
  827.     info := inf
  828.     po := pstr
  829.     end setup
  830.  
  831.     print = proc(o: _obj, nth: int)
  832.     ithops: anop := debugopget_nth_op(info.g_vals, nth)
  833.        except when not_found (ops_name:string):
  834.                ithops := _cvt[int, _vec[_obj]]
  835.                      (inst_from_name(ops_name, info,
  836.                              tparms, oparms))
  837.           end
  838.     print_result(po, o, ithops)
  839.     end print
  840.  
  841.     end iter_yield
  842.  
  843. print_result = proc(pst: pstream, val: _obj, p: _vec[_obj])
  844.     pstream$start(pst, ": ")
  845.     debugopprint_val2(pst, val, p)
  846.     pstream$stop(pst, "")
  847.     pstream$pause(pst, "")
  848.     end print_result
  849.  
  850.